package com.ruoyi.biz.api.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpStatus;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.biz.api.annotation.Log;
import com.ruoyi.biz.api.service.TokenApiService;
import com.ruoyi.biz.api.util.WxUtils;
import com.ruoyi.biz.domain.User;
import com.ruoyi.biz.dto.RegisterDTO;
import com.ruoyi.biz.dto.UserDTO;
import com.ruoyi.biz.param.AutomaticLoginParam;
import com.ruoyi.biz.param.LoginParam;
import com.ruoyi.biz.param.LoginPassword;
import com.ruoyi.biz.service.ISmsCodeService;
import com.ruoyi.biz.service.IUserService;
import com.ruoyi.common.core.domain.ApiResult;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName : WeChatMiniProgramController
 * @Description : 微信小程序登录
 * @Author : Fly
 * @Date: 2021-01-26 15:11
 */


@RestController
@Slf4j
@RequestMapping("/api/login")
@Api(tags = {"登录接口"})
public class LoginApiController {
    @Autowired
    private TokenApiService tokenApiService;

    @Autowired
    private IUserService userService;

    @Autowired
    private ISmsCodeService smsCodeService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 小程序基于code的登入
     * @param loginParam 登入参数
     * @return 服务器端生成token，用于下次快速登入
     */
    @ApiOperation("小程序基于微信code登入")
    @PostMapping
    @Log
    public ApiResult<User> login(@RequestBody LoginParam loginParam) {
        JSONObject authInfo = WxUtils.getAuthInfo(loginParam.getCode());
        User user = new User();
        user.setOpenid(authInfo.getString(WxUtils.OPENID));
        List<User> userList = userService.selectUserList(user);

        if (userList.isEmpty() && (StringUtils.isEmpty(loginParam.getEncryptedData()) || StringUtils.isEmpty(loginParam.getIv()))) {
            return ApiResult.error(HttpStatus.HTTP_ACCEPTED, "未授权微信用户信息");
        }

        long expireTime = new Date().getTime() + (int) TimeUnit.MINUTES.toMillis(tokenApiService.getExpireTime());
        if (userList.isEmpty()) {
            JSONObject userInfo = WxUtils.getWxUserInfo(loginParam.getEncryptedData(), loginParam.getIv(), authInfo.getString(WxUtils.SESSION_KEY));
            user.setOpenid(authInfo.getString(WxUtils.OPENID));
            user.setNickname(userInfo.getString(WxUtils.NICK_NAME));
            user.setTokenExpiredDate(new Date(expireTime));
            user.setRegisterTime(new Date());
            user.setLoginTime(new Date());
            user.setAvatar(userInfo.getString(WxUtils.AVATAR_URL));
            userService.insertUser(user);
            user.setToken(tokenApiService.createToken(String.valueOf(user.getId())));
        }else {
            user = userList.get(0);
            user.setToken(tokenApiService.createToken(String.valueOf(user.getId())));
            user.setTokenExpiredDate(new Date(expireTime));
            user.setLoginTime(new Date());
            userService.updateUser(user);
        }
        tokenApiService.setLoginUser(user);
        return ApiResult.success(user);
    }


    @ApiOperation("发送手机验证码")
    @GetMapping("/smsCode")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone",value = "手机号",dataType = "int",example = "13700000000",required = true)
    })
    public ApiResult smsCode(String phone){
        ApiResult ajax = ApiResult.success();
        User user = new User();
        user.setPhone(phone);
        int smsResult = smsCodeService.sendSmsCode(phone);
        if (smsResult == 1){
            ajax = ApiResult.error("已达到今日发送短信上限");
        }else if (smsResult == 2){
            ajax = ApiResult.error("发送短信过于频繁");
        }
        return ajax;
    }


    @ApiOperation("注册登录接口")
    @PostMapping("/register")
    @Log
    public ApiResult<UserDTO>  register(@RequestBody RegisterDTO registerDTO){
        if (!smsCodeService.validCode(registerDTO.getPhone(), registerDTO.getCode())) {
            return ApiResult.error("验证码无效");
        }
        User user = new User();
        user.setPhone(registerDTO.getPhone());
        List<User> users = userService.selectUserList(user);
        if (!users.isEmpty()){
            user = users.get(0);
        }else {
            user.setRegisterTime(new Date());
            user.setAvatar("https://minip-data.blueasiainfo.com/prod-api/profile/upload/default-avatar.png");
            userService.insertUser(user);
            user = userService.selectUserById(user.getId());
        }
        String token = tokenApiService.createToken(String.valueOf(user.getId()));
        return setUserToken(user, token);
    }


    @ApiOperation("自动登录")
    @GetMapping
    @Log
    public ApiResult<UserDTO> automaticLogin(AutomaticLoginParam automaticLoginParam){
        if (StringUtils.isEmpty(automaticLoginParam.getPhone()) || StringUtils.isEmpty(automaticLoginParam.getVersion())) {
            return  ApiResult.error(500,"缺少参数");
        }
        User user = userService.selectUserByPhone(automaticLoginParam.getPhone());
        if (ObjectUtil.isNotEmpty(user)){
            String token = tokenApiService.createToken(String.valueOf(user.getId()));
            return setUserToken(user,token);
        }else {
            user = new User();
            user.setRegisterTime(new Date());
            user.setPhone(automaticLoginParam.getPhone());
            user.setAvatar("https://minip-data.blueasiainfo.com/prod-api/profile/upload/default-avatar.png");
            userService.insertUser(user);
            String token = tokenApiService.createToken(String.valueOf(user.getId()));
            return setUserToken(user,token);
        }
    }

    @ApiOperation("手机密码登录接口")
    @PostMapping("/password")
    @Log
    public ApiResult<UserDTO> loginPassword(@RequestBody LoginPassword loginPassword){
        User user = new User();
        user.setPhone(loginPassword.getPhone());
        List<User> users = userService.selectUserList(user);
        if (!users.isEmpty())user = users.get(0);
        else return ApiResult.error("没有该手机号");
        if (!SecurityUtils.matchesPassword(loginPassword.getPassword(),user.getPassword())){
            return ApiResult.error("密码错误");
        }
        String token = tokenApiService.createToken(String.valueOf(user.getId()));
        return setUserToken(user, token);
    }


    private ApiResult<UserDTO> setUserToken(User user, String token) {
        int millis = (int) TimeUnit.MINUTES.toMillis(tokenApiService.getExpireTime());
        Date date = new Date();
        long l = date.getTime() + millis;
        user.setToken(token);
        user.setTokenExpiredDate(new Date(l));
        user.setLoginTime(new Date());
        userService.updateUser(user);
        tokenApiService.setLoginUser(user);
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
        return ApiResult.success(userDTO);
    }


}
